home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / du_lib / windial.c < prev   
C/C++ Source or Header  |  1995-07-10  |  21KB  |  868 lines

  1. /*
  2.   DU_LIB v2
  3.   Gem Window Management & Dialog Library For Lattice C
  4.   ½1994, by Craig Graham.
  5.   
  6.   Based on the DU_LIBv1 Library for HiSoft Basic.
  7. */
  8.  
  9. /*
  10.   Windowed Dialog Handlers
  11. */
  12.  
  13. #include "dulib.h"
  14.  
  15. #ifndef cg_graf_watchbox
  16. short cg_graf_watchbox(OBJECT *dial, short ob, short i, short o);
  17. #endif
  18.  
  19. short called_from_process_win_dial=FALSE;
  20. GRECT button_clip;
  21. GRECT button_dclip;
  22.  
  23. /*==========================================
  24.  = Open a non-blocking dialog in a window  =
  25.  =  ½21/8/1994, Craig Graham                =
  26.  ===========================================*/
  27.  
  28. short activate_dialog(short dialog, char *n, dialog_type t)
  29. {
  30.     OBJECT *a;
  31.     short x,y,rx,ry,rw,rh;
  32.     short sx,sy,sw,sh;
  33.     short wh,tp;
  34.     Wtype wt;
  35.  
  36. /* Is tool bar already open ? - if so, then top it. */
  37.     x=-1;
  38.     for (y=0; y<max_windows;y++)
  39.     {
  40.         if ((((windows[y].window_type==wt_dialog)
  41.             ||(windows[y].window_type==wt_dialog_side_bar))
  42.             ||(windows[y].window_type==wt_dialog_bottom_bar))
  43.             &&(windows[y].the_dialog==dialog))
  44.         {
  45.             x=y;
  46.         }
  47.     }
  48.     
  49.     wind_get(0,WF_WORKXYWH,&sx,&sy,&sw,&sh);
  50.     
  51.     if (x!=-1)
  52.     {
  53.         wind_set(x,WF_TOP,0,0,0,0);
  54.         return 1;
  55.     }else{
  56. /* Get size of dialog */
  57.         rsrc_gaddr(0,dialog,&a);
  58.         rx=ry=rw=rh=0;
  59.         
  60.         wt=wt_dialog;
  61. /*Open the window*/
  62.         switch (t)
  63.         {
  64.             case DIAL_FIXED:
  65.                 tp=NAME;
  66.                 wt=wt_static_menu;
  67.                 break;
  68.             case DIAL_NO_CLOSE:
  69.                 tp=NAME+MOVER;
  70.                 wt=wt_dialog;
  71.                 break;
  72.             case DIAL_WIDGET_BAR:
  73.                 tp=NAME+CLOSER+FULLER+MOVER+SIZER+UPARROW+DNARROW+VSLIDE+LFARROW+RTARROW+HSLIDE+SMALLER;
  74.                 wt=wt_drawing;
  75.                 break;
  76.             case DIAL_ROLLUP_SIDE_SCROLLER:
  77.                 tp=NAME+CLOSER+FULLER+MOVER+UPARROW+DNARROW+VSLIDE+SMALLER;
  78.                 wt=wt_dialog_side_bar;
  79.                 break;
  80.             case DIAL_ROLLUP_BOTTOM_SCROLLER:
  81.                 tp=NAME+CLOSER+FULLER+MOVER+LFARROW+RTARROW+HSLIDE+SMALLER;
  82.                 wt=wt_dialog_bottom_bar;
  83.                 break;
  84.             case DIAL_ROLLUP:
  85.                 tp=NAME+CLOSER+FULLER+MOVER+SMALLER;
  86.                 wt=wt_dialog;
  87.                 break;
  88.         }
  89.         form_center(a,&rx,&ry,&rw,&rh);
  90.         wind_calc(0,tp,rx,ry,rw,rh,&rx,&ry,&rw,&rh);
  91.         
  92.         if ((rx+rw)>(sx+sw))
  93.         {
  94.             rx=sx; rw=sw;
  95.         }
  96.         if ((ry+rh)>(sy+sh))
  97.         {
  98.             ry=sy; rh=sh;
  99.         }
  100.  
  101.         wh=wind_create(tp,rx,ry,rw,rh);
  102.         if (wh)
  103.         {
  104.             wind_set(wh,WF_NAME, ADDR(n));
  105.             wind_open(wh,rx,ry,rw,rh);
  106.         
  107.             windows[wh].window_type=wt;
  108.             windows[wh].the_dialog=dialog;
  109.             windows[wh].redraw_mode=wrm_window;
  110.  
  111.             udw=0;
  112.  
  113.             display_dial(wh);
  114.             last_opened_window=wh;
  115.         }
  116.     }
  117.     return wh;
  118. }
  119.  
  120. /*==============================
  121.    Close all copies of a Dialog
  122.   ==============================*/
  123. short close_dialog(short dialog)
  124. {
  125.     short y;
  126.  
  127. /* Is dialog open ? - if so, then close it. */
  128.     for (y=0; y<max_windows;y++)
  129.         if ((windows[y].window_type!=wt_null) && (windows[y].the_dialog==dialog))
  130.             close_dialog_window(y);
  131.     return 0;
  132. }
  133.  
  134. /*==============================
  135.    Close a Dialog Window
  136.   ==============================*/
  137. short close_dialog_window(short e_wind)
  138. {
  139.     windows[e_wind].the_dialog=0;
  140.     windows[e_wind].window_type=wt_null;
  141.     
  142.     graf_mouse(M_OFF,NULL);
  143.     wind_close(e_wind);
  144.     wind_delete(e_wind);
  145.     graf_mouse(M_ON,NULL);
  146.     return 0;
  147. }
  148.  
  149. short set_window_title(short h, char *a)
  150. {
  151.     wind_set(h,WF_NAME,ADDR(a));
  152.     return 0;
  153. }
  154.  
  155. /*===========================================
  156.   = Display a win_dialog window (clipped)   =
  157.   ===========================================*/
  158. short display_dial(short wind_handle)
  159. {
  160.     short x,y,w,h;
  161.     short rw,rh,dialog,rx,ry;
  162.     short dx,dy,dw,dh;
  163.     short cb,top_wind;
  164.     OBJECT *a;
  165.  
  166.     cb=wmi_total_buffering;
  167.     wmi_total_buffering=0;
  168.     
  169.     dx=dy=dw=dh=0;
  170.     
  171. /*    vst_point(12);*/
  172.  
  173.     dialog=windows[wind_handle].the_dialog;
  174.  
  175.     rsrc_gaddr(0,dialog,&a);
  176.     wind_get(wind_handle,WF_WORKXYWH,&x,&y,&w,&h);
  177.  
  178.     if (h!=0)
  179.     {
  180.         wind_get(wind_handle,WF_TOP,&top_wind,0,0,0);
  181.         a->ob_x=x;
  182.         a->ob_y=y;
  183.         graf_mouse(M_OFF,NULL);
  184.         wind_update(BEG_UPDATE);
  185.         
  186.         if (wind_handle==top_wind)
  187.         {
  188.             cr_dclip.g_x=x;
  189.             cr_dclip.g_y=y;
  190.             cr_dclip.g_w=w;
  191.             cr_dclip.g_h=h;
  192.             objc_draw(a,0,5,x,y,w,h);
  193.             redraw_custom(wind_handle);
  194.         }else{
  195.             wind_get(wind_handle,WF_FIRSTXYWH,&rx,&ry,&rw,&rh);
  196.             while (rw>0 && rh>0)
  197.             {
  198.                 dx=rx;dy=ry;dw=rw;dh=rh;
  199.                 if (udw!=0)
  200.                 {
  201.                     if (intersection(rx,ry,rw,rh,udx,udy,udw,udh,&dx,&dy,&dw,&dh))
  202.                     {
  203.                         cr_dclip.g_x=dx;
  204.                         cr_dclip.g_y=dy;
  205.                         cr_dclip.g_w=dw;
  206.                         cr_dclip.g_h=dh;
  207.                         objc_draw(a,0,5,dx,dy,dw,dh);
  208.                         redraw_custom(wind_handle);
  209.                     }
  210.                 }
  211.             
  212.                 wind_get(wind_handle,WF_NEXTXYWH,&rx,&ry,&rw,&rh);
  213.             }
  214.         }
  215.         wind_update(END_UPDATE);
  216.         graf_mouse(M_ON,NULL);
  217.     }
  218.     
  219.     wmi_total_buffering=cb;    
  220.     return 0;
  221. }
  222.  
  223. /*=========================================================================
  224.   = Re-display only the custom objects in a win_dialog window (clipped)   =
  225.   =========================================================================*/
  226. short custom_display_dial(short wind_handle)
  227. {
  228.     short wx,wy,ww,wh;
  229.     short rw,rh,dialog,rx,ry;
  230.     short dx,dy,dw,dh;
  231.     short cb;
  232.     OBJECT *a;
  233.     short clip[4];
  234.     CallBack rd;
  235.     Elist *e;
  236.     GRECT r;
  237. #ifdef __USE_GNU
  238.     short x,y;
  239. #endif    
  240.  
  241.     cb=wmi_total_buffering;
  242.     wmi_total_buffering=0;
  243.     
  244.     dx=dy=dw=dh=0;
  245.     
  246.     dialog=windows[wind_handle].the_dialog;
  247.     this_dialog=dialog;
  248.     cr_wind_handle=wind_handle;
  249.  
  250.     rsrc_gaddr(0,dialog,&a);
  251.     wind_get(wind_handle,WF_WORKXYWH,&wx,&wy,&ww,&wh);
  252.  
  253.     if (wh!=0)
  254.     {
  255.         a->ob_x=wx;
  256.         a->ob_y=wy;
  257.  
  258.         graf_mouse(M_OFF,NULL);
  259.         wind_update(BEG_UPDATE);
  260.  
  261.         wind_get(wind_handle,WF_FIRSTXYWH,&rx,&ry,&rw,&rh);
  262.         while (rw>0 && rh>0)
  263.         {
  264.             dx=rx;dy=ry;dw=rw;dh=rh;
  265.             if (udw!=0)
  266.             {
  267.                 if (intersection(rx,ry,rw,rh,udx,udy,udw,udh,&dx,&dy,&dw,&dh))
  268.                 {
  269.                     cr_dclip.g_x=dx;
  270.                     cr_dclip.g_y=dy;
  271.                     cr_dclip.g_w=dw;
  272.                     cr_dclip.g_h=dh;
  273.     
  274.                     r=cr_dclip;
  275.     
  276.                     e=event_value[dialog];
  277.                     if (e!=0)
  278.                     {
  279.                         for(; e!=0; e=e->next)
  280.                         {
  281.                             rd=e->redraw;
  282.                             if (rd)
  283.                             {
  284.                                 this_ob=e->object;
  285. #ifndef __USE_GNU
  286.                                 objc_xywh(a,this_ob,&cr_clip);
  287.                                 cr_clip.g_w--;
  288.                                 cr_clip.g_h--;
  289. #else
  290.                                 objc_offset(a,this_ob,&x,&y);
  291.                                 cr_clip.g_x=x;
  292.                                 cr_clip.g_y=y;
  293.                                 cr_clip.g_w=(a+this_ob)->ob_width;
  294.                                 cr_clip.g_h=(a+this_ob)->ob_height;
  295. #endif
  296.                                 cr_dclip=r;
  297.                                 if (rc_intersect(&cr_clip,&cr_dclip))
  298.                                 {
  299.                                     clip[0]=cr_dclip.g_x; clip[1]=cr_dclip.g_y;
  300.                                     clip[2]=cr_dclip.g_x+cr_dclip.g_w-1; clip[3]=cr_dclip.g_y+cr_dclip.g_h-1;
  301.                                     vs_clip(x_handle,1,clip);
  302.                                     objc_draw(a,this_ob,1,dx,dy,dw,dh);
  303.                                     (*rd)();
  304.                                 }
  305.                             }
  306.                         }
  307.                     }
  308.                 }
  309.             }
  310.             
  311.             wind_get(wind_handle,WF_NEXTXYWH,&rx,&ry,&rw,&rh);
  312.         }
  313.  
  314.         wind_update(END_UPDATE);
  315.         graf_mouse(M_ON,NULL);
  316.  
  317.     }
  318.     
  319.     wmi_total_buffering=cb;    
  320.     return 0;
  321. }
  322.  
  323. /*=========================================================================
  324.   = Re-display only a specified object in a win_dialog window (clipped)  =
  325.   =========================================================================*/
  326. short wind_display_object(short wind_handle, short object)
  327. {
  328.     short wx,wy,ww,wh;
  329.     short rw,rh,dialog,rx,ry;
  330.     short dx,dy,dw,dh;
  331.     short cb;
  332.     OBJECT *a;
  333.     short clip[4];
  334.     CallBack rd;
  335.     GRECT r;
  336. #ifdef __USE_GNU
  337.     short x,y;
  338. #endif    
  339.     cb=wmi_total_buffering;
  340.     wmi_total_buffering=0;
  341.     
  342.     dx=dy=dw=dh=0;
  343.     
  344.     dialog=windows[wind_handle].the_dialog;
  345.     this_dialog=dialog;
  346.     this_ob=object;
  347.     cr_wind_handle=wind_handle;
  348.  
  349.     rsrc_gaddr(0,dialog,&a);
  350.     wind_get(wind_handle,WF_WORKXYWH,&wx,&wy,&ww,&wh);
  351.  
  352.     if (wh!=0)
  353.     {
  354.         a->ob_x=wx;
  355.         a->ob_y=wy;
  356.  
  357.         rd=Get_object_redraw(dialog, object);
  358.         
  359.         graf_mouse(M_OFF,NULL);
  360.         wind_update(BEG_UPDATE);
  361.         
  362.         wind_get(wind_handle,WF_FIRSTXYWH,&rx,&ry,&rw,&rh);
  363.         while (rw>0 && rh>0)
  364.         {
  365.             dx=rx;dy=ry;dw=rw;dh=rh;
  366.             if (intersection(rx,ry,rw,rh,scrn_x,scrn_y,scrn_w,scrn_h,&dx,&dy,&dw,&dh))
  367.             {
  368.                 cr_dclip.g_x=dx;
  369.                 cr_dclip.g_y=dy;
  370.                 cr_dclip.g_w=dw;
  371.                 cr_dclip.g_h=dh;
  372.                 r=cr_dclip;
  373. #ifndef __USE_GNU
  374.                 objc_xywh(a,this_ob,&cr_clip);
  375.                 cr_clip.g_w--;
  376.                 cr_clip.g_h--;
  377. #else
  378.                 objc_offset(a,this_ob,&x,&y);
  379.                 cr_clip.g_x=x;
  380.                 cr_clip.g_y=y;
  381.                 cr_clip.g_w=(a+this_ob)->ob_width;
  382.                 cr_clip.g_h=(a+this_ob)->ob_height;
  383. #endif
  384.                 cr_dclip=r;
  385.                 if (rc_intersect(&cr_clip,&cr_dclip))
  386.                 {
  387.                     clip[0]=cr_dclip.g_x; clip[1]=cr_dclip.g_y;
  388.                     clip[2]=cr_dclip.g_x+cr_dclip.g_w-1; clip[3]=cr_dclip.g_y+cr_dclip.g_h-1;
  389.                     vs_clip(x_handle,1,clip);
  390.                     if (called_from_process_win_dial)
  391.                         objc_draw(a,this_ob,1,rx,ry,rw,rh);
  392.                     else
  393.                         objc_draw(a,this_ob,1,cr_dclip.g_x,cr_dclip.g_y,cr_dclip.g_w,cr_dclip.g_h);
  394.                     if (rd)    /*If a custom redraw exists, use it*/
  395.                         (*rd)();
  396.                 }
  397.             }
  398.             wind_get(wind_handle,WF_NEXTXYWH,&rx,&ry,&rw,&rh);
  399.         }
  400.  
  401.         wind_update(END_UPDATE);
  402.         graf_mouse(M_ON,NULL);
  403.  
  404.     }
  405.     
  406.     wmi_total_buffering=cb;    
  407.     return 0;
  408. }
  409.  
  410. /*====================================================================================
  411.   = Re-display only the a specified custom object in a win_dialog window (clipped)   =
  412.   ====================================================================================*/
  413. short custom_display_object(short wind_handle, short ob)
  414. {
  415.     wind_display_object(wind_handle, ob);
  416.     return 0;
  417. }
  418.  
  419. int intersection(short x1,short y1,short w1,short h1,short x2,short y2,short w2,short h2,short *x,short *y,short *w,short *h)
  420. {
  421.     GRECT a,b;
  422.     int r;
  423.     
  424.     a.g_x=x2; a.g_y=y2; a.g_w=w2; a.g_h=h2;
  425.     b.g_x=x1; b.g_y=y1; b.g_w=w1; b.g_h=h1;
  426.     
  427.     r=rc_intersect(&a,&b);
  428.     
  429.     *x=b.g_x; *y=b.g_y; *w=b.g_w; *h=b.g_h;
  430.     
  431.     return r;
  432. }
  433.  
  434. /* Update a dialog (if it is open)*/
  435. short dialog_update(short d)
  436. {
  437.     short n,rtn;
  438.     rtn=0;
  439.     for(n=0; n<max_windows; n++)
  440.     {
  441.         if ((windows[n].window_type!=wt_null)&&(windows[n].the_dialog==d))
  442.         { 
  443.             rtn=update_window(n); 
  444.         }
  445.     }
  446.     return rtn;
  447. }
  448.  
  449. short dialog_display(short d)
  450. {
  451.     short n,rtn;
  452.  
  453.     rtn=0;
  454.     udx=scrn_x; udy=scrn_y; udw=scrn_w; udh=scrn_h;
  455.     
  456.     for(n=0; n<max_windows; n++)
  457.     {
  458.         if ((windows[n].window_type!=wt_null)&&(windows[n].the_dialog==d))
  459.         {
  460.             rtn=display_dial(n);
  461.         }
  462.     }
  463.     return rtn;
  464. }
  465.  
  466. short dialog_object_display(short d, short o)
  467. {
  468.     short n,rtn;
  469.  
  470.     rtn=0;
  471.     udx=scrn_x; udy=scrn_y; udw=scrn_w; udh=scrn_h;
  472.     
  473.     for(n=0; n<max_windows; n++)
  474.     {
  475.         if ((windows[n].window_type!=wt_null)&&(windows[n].the_dialog==d))
  476.         {
  477.             rtn=wind_display_object(n,o);
  478.         }
  479.     }
  480.     return rtn;
  481. }
  482.  
  483. int redraw_custom(short wind_handle)
  484. {
  485.     OBJECT *a;
  486.     short clip[4];
  487.     CallBack rd;
  488.     short dialog;
  489.     Elist *e;
  490.     GRECT r;
  491. #ifdef __USE_GNU
  492.     short x,y;
  493. #endif    
  494.     
  495.     dialog=windows[wind_handle].the_dialog;
  496.     rsrc_gaddr(0,dialog,&a);
  497.  
  498.     this_dialog=dialog;
  499.     cr_wind_handle=wind_handle;
  500.     r=cr_dclip;
  501.     
  502.     e=event_value[dialog];
  503.     if (e!=0)
  504.     {
  505.         for(; e!=0; e=e->next)
  506.         {
  507.             rd=e->redraw;
  508.             if (rd)
  509.             {
  510.                 this_ob=e->object;
  511. #ifndef __USE_GNU
  512.                 objc_xywh(a,this_ob,&cr_clip);
  513.                 cr_clip.g_w--;
  514.                 cr_clip.g_h--;
  515. #else
  516.                 objc_offset(a,this_ob,&x,&y);
  517.                 cr_clip.g_x=x;
  518.                 cr_clip.g_y=y;
  519.                 cr_clip.g_w=(a+this_ob)->ob_width;
  520.                 cr_clip.g_h=(a+this_ob)->ob_height;
  521. #endif
  522.                 cr_dclip=r;
  523.                 if (rc_intersect(&cr_clip,&cr_dclip))
  524.                 {
  525.                     clip[0]=cr_dclip.g_x; clip[1]=cr_dclip.g_y;
  526.                     clip[2]=cr_dclip.g_x+cr_dclip.g_w-1; clip[3]=cr_dclip.g_y+cr_dclip.g_h-1;
  527.                     vs_clip(x_handle,1,clip);
  528.                     (*rd)();
  529.                 }
  530.             }
  531.         }
  532.     }
  533.  
  534.     return 0;
  535. }
  536.  
  537. /*==================================================================
  538.   = Perform processing on a dialog in a window.                    =
  539.   =  When passed an MU_BUTTON event for a dialog window, this      =
  540.   =  will perfrom processing on that dialog (radio buttons, etc)   =
  541.   =  and will return 0 if the dialog did NOT exit, else the object =
  542.   =  number exitted on.                                            =
  543.   ==================================================================*/
  544. short process_win_dial(short wh,short x,short y)
  545. {
  546.     short ob,mb,Obflags,dx,dy,wdx,wdy,wdw,wdh;
  547.     short a,rtn,ReallySelected;
  548.     short obx,oby,obw,obh;
  549.     short clip[4];
  550.     OBJECT *TheDial;
  551.     OBJECT *TheObject;
  552.     Elist *ipopup_scan;
  553.     CallBack custom_handler;
  554.     CallBack dcustom_handler;
  555.     CallBack rd;
  556. #ifdef __USE_GNU
  557.     short cx,cy;
  558. #endif
  559.     called_from_process_win_dial=TRUE;        /* Use button_clip for redrawing buttons instead of 
  560.                                                 cr_clipd to ensure 3D buttons work properly*/
  561.     rtn=0; mb=0;
  562.     a=windows[wh].the_dialog;
  563.     this_dialog=a;
  564.     cr_wind_handle=wh;
  565.     
  566.     rsrc_gaddr(0,a,&TheDial);                            /*Address of dialog in resource*/
  567.  
  568.     wind_get(wh,WF_WORKXYWH,&wdx,&wdy,&wdw,&wdh);        /*Ensure that the dialog is where we think it is          */
  569.     dx=wdx; dy=wdy;
  570.     TheDial->ob_x=dx;                                    /* (fix for multiple copies of a dialog (eg a widget bar) */
  571.     TheDial->ob_y=dy;
  572.  
  573.     ob=objc_find(TheDial, 0, 5, x, y);                    /*Find the object clicked on*/
  574.  
  575.     if (ob>0)
  576.     {
  577.         TheObject=TheDial+ob;
  578.         custom_handler=Get_object_callback(a, ob);        /*Check for a custom object handler (single click)*/
  579.         dcustom_handler=Get_object_dcallback(a, ob);    /*Check for a custom object handler (double click)*/
  580.         rd=Get_object_redraw(a,ob);
  581.         this_ob=ob;
  582. #ifndef __USE_GNU
  583.         objc_xywh(TheDial,this_ob,&cr_clip);
  584.         cr_clip.g_w--;
  585.         cr_clip.g_h--;
  586.         obx=cr_clip.g_x;
  587.         oby=cr_clip.g_y;
  588.         obw=cr_clip.g_w;
  589.         obh=cr_clip.g_h;
  590. #else
  591.         objc_offset(TheDial,this_ob,&cx,&cy);
  592.         obx=cr_clip.g_x=cx;
  593.         oby=cr_clip.g_y=cy;
  594.         obw=cr_clip.g_w=(TheDial+this_ob)->ob_width;
  595.         obh=cr_clip.g_h=(TheDial+this_ob)->ob_height;
  596. #endif
  597.         cr_dclip.g_x=wdx;
  598.         cr_dclip.g_y=wdy;
  599.         cr_dclip.g_w=wdw;
  600.         cr_dclip.g_h=wdh;
  601.  
  602.         cr_mx=x-obx;
  603.         cr_my=y-oby;
  604.  
  605.         button_clip=cr_clip;
  606.         button_dclip=cr_dclip;
  607.         button_clip.g_x-=3;
  608.         button_clip.g_y-=3;
  609.         button_clip.g_w+=6;
  610.         button_clip.g_h+=6;
  611.         
  612.         rc_intersect(&cr_clip,&cr_dclip);
  613.         rc_intersect(&button_clip,&button_dclip);
  614.  
  615.         clip[0]=cr_dclip.g_x; clip[1]=cr_dclip.g_y; clip[2]=cr_dclip.g_x+cr_dclip.g_w-1; clip[3]=cr_dclip.g_y+cr_dclip.g_h-1;
  616.         vs_clip(x_handle,1,clip);
  617.         
  618.         if (((click_count==1)&&(custom_handler!=NULL))||((click_count==2)&&(dcustom_handler!=NULL)))    /*If there is a custom behaviour, use it */
  619.         {
  620.             if (((TheObject->ob_flags&SELECTABLE)==SELECTABLE)&&((TheObject->ob_state&DISABLED)!=DISABLED))        /* Is this a selectable object ?*/
  621.             {
  622.                 if (click_count==2)
  623.                 {
  624.                     ipopup_scan=(Elist*)0;
  625.                     find_event(this_dialog,this_ob,&ipopup_scan);
  626.                     if (!(ipopup_scan->popup_form))
  627.                         TheObject->ob_state=TheObject->ob_state|SELECTED;
  628.                 }else{
  629.                     TheObject->ob_state=TheObject->ob_state|SELECTED;
  630.                 }
  631.                 if ((TheObject->ob_state|SELECTED))        /* Don't select icon popups when they are double clicked on */
  632.                 {
  633.                     graf_mouse(M_OFF,NULL);                                /* Display object as selected */
  634.                     objc_draw(TheDial,ob,1,button_dclip.g_x,button_dclip.g_y,button_dclip.g_w,button_dclip.g_h);
  635.                     if (rd) (*rd)();
  636.                     graf_mouse(M_ON,NULL);
  637.                 }
  638.             }
  639.  
  640.             clip[0]=cr_dclip.g_x; clip[1]=cr_dclip.g_y; clip[2]=cr_dclip.g_x+cr_dclip.g_w-1; clip[3]=cr_dclip.g_y+cr_dclip.g_h-1;
  641.             vs_clip(x_handle,1,clip);
  642.  
  643.             if ((TheObject->ob_state&DISABLED)!=DISABLED)
  644.             {
  645.                 switch(click_count)
  646.                 {
  647.                     case 1:                /* Single click handler ?*/
  648.                         if (custom_handler)
  649.                         {
  650.                             if ((*custom_handler)()) rtn=ob;
  651.                         }
  652.                         break;
  653.                     case 2:                /* Double click handler ?*/
  654.                         if (dcustom_handler)
  655.                         {
  656.                             if ((*dcustom_handler)()) rtn=ob;
  657.                         }
  658.                         break;                        
  659.                 }
  660.             }
  661.         }
  662.  
  663.         clip[0]=cr_dclip.g_x; clip[1]=cr_dclip.g_y; clip[2]=cr_dclip.g_x+cr_dclip.g_w-1; clip[3]=cr_dclip.g_y+cr_dclip.g_h-1;
  664.         vs_clip(x_handle,1,clip);
  665.  
  666.         Obflags=TheObject->ob_flags;
  667.  
  668.         if ((click_count==1)&&((Obflags&DISABLED)!=DISABLED))
  669.         {
  670.             if (!rtn)                                                /* Default behaviour if no custom behaviours have worked */
  671.             {
  672.                 if ((TheObject->ob_flags&SELECTABLE)==SELECTABLE)        /* Is this a selectable object ?*/
  673.                 {
  674.                     TheObject->ob_state=TheObject->ob_state^SELECTED;
  675.                     graf_mkstate(&junk,&junk,&mb,&junk);
  676.  
  677.                     ReallySelected=cg_graf_watchbox(TheDial,ob,TheObject->ob_state,TheObject->ob_state^SELECTED);
  678.  
  679.                     if (!ReallySelected)
  680.                         if ((TheObject->ob_flags&EXIT)==EXIT) Obflags=0;
  681.                     else
  682.                         rtn=ob;
  683.                 }
  684.             }else{
  685.                 ReallySelected=TRUE;
  686.             }
  687.     /* Do radio button behaviour if required, but only for a single click */
  688.             if ((ReallySelected)&&((TheObject->ob_flags&RBUTTON)==RBUTTON))
  689.              {
  690.                 Radio_b(TheDial,ob);
  691.                 for(mb=1; mb;) graf_mkstate(&junk,&junk,&mb,&junk);
  692.                 rtn=ob;                    /* Radio buttons always return their event */
  693.             }
  694.         }
  695.         
  696.         clip[0]=cr_dclip.g_x; clip[1]=cr_dclip.g_y; clip[2]=cr_dclip.g_x+cr_dclip.g_w-1; clip[3]=cr_dclip.g_y+cr_dclip.g_h-1;
  697.         vs_clip(x_handle,1,clip);
  698.         
  699.         graf_mouse(M_OFF,NULL);
  700.         if ((Obflags&EXIT)==EXIT)        /* Exit buttons are always reset & redrawn, no matter what was returned */
  701.         {
  702.             if ((TheObject->ob_flags&RBUTTON)==0)
  703.             {
  704.                 TheObject->ob_state=TheObject->ob_state&~SELECTED;
  705.                 objc_draw(TheDial,ob,1,button_dclip.g_x,button_dclip.g_y,button_dclip.g_w,button_dclip.g_h);
  706.                 if (rd) (*rd)();
  707.             }
  708.             rtn=ob;
  709.         }else{                            /* Custom click handlers may have returned a value - if TRUE then a redraw was requested */
  710.             if ((rtn)&&((custom_handler)||(dcustom_handler)))
  711.             {
  712.                 objc_draw(TheDial,ob,1,button_dclip.g_x,button_dclip.g_y,button_dclip.g_w,button_dclip.g_h);
  713.                 if (rd) (*rd)();
  714.             }
  715.         }
  716.         graf_mouse(M_ON,NULL);
  717.     }
  718.     called_from_process_win_dial=FALSE;
  719.     return rtn;
  720. }
  721.  
  722. /*
  723.   Sets one of a group of radio buttons, and clears the rest.
  724.   Includes patch to allow for pop_icons as radio buttons.
  725. */
  726. short Radio_b(OBJECT *d, short object)
  727. {
  728.     OBJECT *obloc;
  729.     short m,parent,o,tobs;
  730.  
  731.     parent=GetParent(d,object);
  732.     tobs=this_ob;
  733.     
  734.     obloc=d+parent;
  735.     
  736.     udx=scrn_x; udy=scrn_y;
  737.     udw=scrn_w; udh=scrn_h;
  738.     
  739.     o=obloc->ob_head;
  740.     obloc=d+o;
  741.     while ((o!=parent)&&(o!=-1))
  742.     {
  743.         if (((obloc->ob_flags&RBUTTON)==RBUTTON)&&((obloc->ob_state&SELECTED)==SELECTED))
  744.         {
  745.             obloc->ob_state=(obloc->ob_state)&~SELECTED;
  746.             for(m=0; m<max_windows; m++)
  747.                 if ((windows[m].window_type!=wt_null)&&(windows[m].the_dialog==this_dialog))
  748.                     custom_display_object(m,o);
  749.             
  750.         }
  751.         o=obloc->ob_next;
  752.         obloc=d+o;
  753.     }
  754.     obloc=d+object;
  755.     obloc->ob_state=(obloc->ob_state)|SELECTED;
  756.  
  757.     for(m=0; m<max_windows; m++)
  758.         if ((windows[m].window_type!=wt_null)&&(windows[m].the_dialog==this_dialog))
  759.             custom_display_object(m,object);
  760.  
  761.     this_ob=tobs;
  762.     return 0;
  763. }
  764.  
  765. /* Returns the object number of this object's parent or -1 if it is the root*/
  766. short GetParent(OBJECT *t,short object)
  767. {
  768.     short nextobject,n_ob_tail;
  769.     OBJECT* c_obl;
  770.     OBJECT* n_obl;
  771.     
  772.     if (object==0)
  773.     {
  774.         return -1;
  775.     } else {
  776.         do
  777.         {
  778.             c_obl=t+object;
  779.             nextobject=c_obl->ob_next;
  780.             n_obl=t+nextobject;
  781.             n_ob_tail=n_obl->ob_tail;
  782.             if (n_ob_tail!=object) { object=nextobject; }
  783.         }
  784.         while (n_ob_tail!=object);
  785.         return nextobject;
  786.     }
  787. }
  788.  
  789. /* Returns the value of the ob_state,ob_type & ob_flags fields in the given object */
  790. short Get_ob_info(OBJECT *dialog,short ob,short *otype,short *oflags,short *ostate)
  791. {
  792.     OBJECT *a;
  793.     a=dialog+ob;
  794.     *oflags=a->ob_flags;
  795.     *otype=a->ob_type;
  796.     *ostate=a->ob_state;
  797.     return 0;
  798. }
  799.  
  800. /*
  801.     Replacement for graf_watchbox() that does justice to colour icons and 3d objects
  802.     17/5/95
  803. */
  804. short cg_graf_watchbox(OBJECT *dial, short ob, short i, short o)
  805. {
  806.     short pobf,obf,mx,my,mb,e,x,y,w,h;
  807.     
  808.     graf_mkstate(&mx,&my,&mb,&junk);
  809.     
  810.     objc_offset(dial,ob,&x,&y);
  811.     w=(dial+ob)->ob_width+2;
  812.     h=(dial+ob)->ob_height+2;
  813.     x--; y--;
  814.  
  815.     if (!mb)        // If mouse button is already released, assume that was just a click, so select
  816.     {
  817.         (dial+ob)->ob_state=i;
  818.         graf_mouse(M_OFF,NULL);
  819.         if (called_from_process_win_dial)
  820.             objc_draw(dial,ob,1,button_dclip.g_x,button_dclip.g_y,button_dclip.g_w,button_dclip.g_h);
  821.         else
  822.             objc_draw(dial,ob,1,x,y,w,h);
  823.         graf_mouse(M_ON,NULL);
  824.         return TRUE;
  825.     }
  826.     
  827.     wind_update(BEG_UPDATE);
  828.     wind_update(BEG_MCTRL);
  829.  
  830.     pobf=-2;
  831.     while (mb)
  832.     {
  833. #ifndef __USE_GNU
  834.         e=evnt_multi(MU_BUTTON|MU_M1|MU_TIMER, 1, 1, 1, 1, mx, my, 1, 1,0,0,0,0,0,
  835.                 messB,100,0,&mx,&my,&mb,&junk,&junk,&junk);
  836. #else
  837.         e=evnt_multi(MU_BUTTON|MU_M1|MU_TIMER, 1, 1, 1, 1,mx,my,1,1,0,0,0,0,0,
  838.                 messB,100,&mx,&my,&mb,&junk,&junk,&junk);
  839. #endif
  840.         if (!(e&MU_BUTTON)) graf_mkstate(&mx,&my,&mb,&junk);
  841.  
  842.         obf=objc_find(dial,ob,1,mx,my);
  843.  
  844.         if (obf==ob)
  845.             (dial+ob)->ob_state=i;
  846.         else
  847.             (dial+ob)->ob_state=o;
  848.  
  849.         if (pobf!=obf)
  850.         {
  851.             pobf=obf;
  852.             graf_mouse(M_OFF,NULL);
  853.             if (called_from_process_win_dial)
  854.                 objc_draw(dial,ob,1,button_dclip.g_x,button_dclip.g_y,button_dclip.g_w,button_dclip.g_h);
  855.             else
  856.                 objc_draw(dial,ob,1,x,y,w,h);
  857.  
  858.             graf_mouse(M_ON,NULL);
  859.         }
  860.     }
  861.     wind_update(END_MCTRL);
  862.     wind_update(END_UPDATE);
  863.  
  864.     if (obf==ob)
  865.         return 1;
  866.     else
  867.         return 0;
  868. }